//
//  NSArray+Safe.m
//  niuguwang
//
//  Created by BrightLi on 2021/5/15.
//  Copyright © 2021年 taojinzhe. All rights reserved.
//

#import "NSArray+Safe.h"
#import <UIKit/UIKit.h>
#import "YMSafeUtil.h"

@implementation NSArray(Safe)

+ (void) safe_fixed
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [YMSafeUtil swizzleClass:[self class]
                  sel1:@selector(arrayWithObjects:count:)
                  sel2:@selector(safe_arrayWithObjects:count:)];
        [YMSafeUtil swizzleInstance:[self class]
                  sel1:@selector(objectsAtIndexes:)
                  sel2:@selector(safe_objectAtIndexes:)];
        [YMSafeUtil swizzleInstance:[self class]
                  sel1:@selector(arrayByAddingObject:)
                  sel2:@selector(safe_arrayByAddingObject:)];
        [YMSafeUtil swizzleInstance:[self class]
                  sel1:@selector(subarrayWithRange:)
                  sel2:@selector(safe_subarrayWithRange:)];
        [YMSafeUtil swizzleInstance:NSClassFromString(@"__NSArrayI")
                  sel1:@selector(objectAtIndex:)
                  sel2:@selector(safe_objectAtIndex:)];
        [YMSafeUtil swizzleInstance:NSClassFromString(@"__NSArrayI")
                  sel1:@selector(objectAtIndexedSubscript:)
                  sel2:@selector(safe_objectAtIndexedSubscript:)];
        [YMSafeUtil swizzleInstance:NSClassFromString(@"__NSArrayI")
                  sel1:@selector(getObjects:range:)
                  sel2:@selector(safe_getObjects:range:)];
        float ios=[[[UIDevice currentDevice] systemVersion] floatValue];
        // iOS10以上，单个元素的数组类型是 __NSSingleObjectArrayI
        if(ios>10.0f){
            [YMSafeUtil swizzleInstance:NSClassFromString(@"__NSSingleObjectArrayI")
                      sel1:@selector(objectAtIndex:)
                      sel2:@selector(safe_objectAtIndex1:)];
        }
        // iOS9以上,空数组类型是 __NSArray0
        if(ios>=9.0f){
            [YMSafeUtil swizzleInstance:NSClassFromString(@"__NSArray0")
                      sel1:@selector(objectAtIndex:)
                      sel2:@selector(safe_objectAtIndex0:)];
        }
    });
}

+ (instancetype) safe_arrayWithObjects:(const id  _Nonnull __unsafe_unretained *)objects count:(NSUInteger) cnt
{
    id instance = nil;
    NSInteger newObjsIndex = 0;
    id _Nonnull __unsafe_unretained newObjects[cnt];
    for (int i = 0; i < cnt; i++) {
        if (objects[i] != nil) {
            newObjects[newObjsIndex] = objects[i];
            newObjsIndex++;
        }
    }
    instance = [self safe_arrayWithObjects:newObjects count:newObjsIndex];
    return instance;
}

- (NSArray *) safe_arrayByAddingObject:(id)anObject
{
    if(!anObject){
        return self;
    }
    return [self safe_arrayByAddingObject:anObject];
}

- (id) safe_objectAtIndex:(NSUInteger)index
{
    @autoreleasepool{
        if(index>=self.count){
            NSString *info=[NSString stringWithFormat:@"[__NSArrayI objectAtIndex:]索引[%tu]越界[%tu]",
                            index,self.count];
            [YMSafeUtil log:@"%@", info];
            return nil;
        }
        return  [self safe_objectAtIndex:index];
    }
}
- (id) safe_objectAtIndexedSubscript:(NSUInteger) index
{
    if(index>=self.count){
        NSString *info=[NSString stringWithFormat:@"! [__NSArrayI objectAtIndexedSubscript:]索引[%tu]越界[%tu]",index,self.count];
        [YMSafeUtil log:@"%@", info];
        return nil;
    }
    return  [self safe_objectAtIndexedSubscript:index];
}
// __NSSingleObjectArrayI 只有一个元素
- (id) safe_objectAtIndex1:(NSUInteger)index
{
    if(index>=self.count)
    {
        NSString *info=[NSString stringWithFormat:@"[__NSSingleObjectArrayI objectAtIndex:]索引[%tu]越界[%tu]",
                        index,self.count];
        [YMSafeUtil log:@"%@", info];
        return nil;
        return nil;
    }
    return [self safe_objectAtIndex1:index];
}
// __NSArray0 没有元素，也不可以改变
- (id) safe_objectAtIndex0:(NSUInteger)index
{
    NSString *info=[NSString stringWithFormat:@"[__NSArray0 objectAtIndex:] 无效的索引:%tu",index];
    [YMSafeUtil log:@"%@", info];
    return nil;
}

- (NSArray *) safe_subarrayWithRange:(NSRange )range
{
    if(range.location+range.length<=self.count){
        return [self safe_subarrayWithRange:range];
    }else if(range.location<self.count){
        return [self safe_subarrayWithRange:NSMakeRange(range.location, self.count-range.location)];
    }
    NSString *info=[NSString stringWithFormat:@"[NSArray subarrayWithRange:] 索引超出范围:{%tu,%tu}",
                    range.location,range.length];
    [YMSafeUtil log:@"%@", info];
    return nil;
}

- (void) safe_getObjects:(__unsafe_unretained id _Nonnull *)objects
                range:(NSRange)range
{
    @try {
        [self safe_getObjects:objects range:range];
    } @catch (NSException *exception) {
        [YMSafeUtil stackLog:exception start:3];
    } @finally {
    }
}

- (NSArray *) safe_objectAtIndexes:(NSIndexSet *)indexes
{
    if(!indexes || [self count]<1){
        return [[NSArray alloc] init];
    }
    __block NSMutableArray *result=[[NSMutableArray alloc] init];
#if __has_feature(objc_arc)
    __weak typeof(self) weakSelf=self;
#else
    __block typeof(self) weakSelf=self;
#endif
    [indexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
        if(idx<[self count]){
            [result addObject:[weakSelf objectAtIndex:idx]];
        }
    }];
    return [result copy];
}

@end
